// Command.java
package org.zjx.command;

import lombok.Getter;
import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zjx.core.IWindow;
import org.zjx.manager.ActivationManager;
import org.zjx.state.StateManager;

import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 命令抽象基类 - 改进中断处理和资源管理
 */
@Getter
public abstract class Command implements ICommand {
    private static final Logger logger = LoggerFactory.getLogger(Command.class);
    protected final StateManager stateManager;
    protected final IWindow targetWindow;
    private final String commandName;
    private final boolean requiresActiveWindow;
    private final AtomicBoolean executed = new AtomicBoolean(false);

    // 重试配置
    private int maxRetries = 0;
    private long retryDelay = 1000;

    public Command(IWindow targetWindow, boolean requiresActiveWindow,StateManager stateManager) {
        if (targetWindow == null) {
            throw new IllegalArgumentException("目标窗口不能为空");
        }
        this.targetWindow = targetWindow;
        this.requiresActiveWindow = requiresActiveWindow;
        this.commandName = this.getClass().getSimpleName();
        this.stateManager = stateManager;
    }

    @SneakyThrows
    @Override
    public final boolean execute(){
        // 防止重复执行
        if (!executed.compareAndSet(false, true)) {
            logger.warn("[命令] 命令已被执行，跳过: {}", commandName);
            return false;
        }

        boolean activationAcquired = false;
        int retryCount = 0;

        do {
            try {
                // 每次重试前检查中断
                checkInterruption();

                // 获取窗口激活权
                if (requiresActiveWindow) {
                    activationAcquired = ActivationManager.requestActivation(targetWindow);
                    if (!activationAcquired) {
                        throw new RuntimeException("获取窗口激活权失败");
                    }
                }

                // 执行前再次检查中断
                checkInterruption();

                // 执行具体命令逻辑
                doExecute();

                // 成功执行，释放激活权
                if (activationAcquired) {
                    ActivationManager.releaseActivation(targetWindow);
                    activationAcquired = false;
                }
                return true;

            } catch (InterruptedException e) {
                // 中断异常直接抛出
                logger.warn("[命令] 执行被中断: {}", commandName);
                cleanup(activationAcquired);
                throw e;
            } catch (Exception e) {
                logger.error("[命令] 执行失败 {} (重试 {}/{}): {}",
                        commandName, retryCount, maxRetries, e.getMessage());

                // 清理资源
                cleanup(activationAcquired);
                activationAcquired = false;

                // 检查中断
                if (isInterrupted()) {
                    logger.warn("[命令] 执行过程中被中断: {}", commandName);
                    throw new InterruptedException("命令执行被中断");
                }

                // 重试逻辑
                if (retryCount < maxRetries) {
                    retryCount++;
                    if (retryDelay > 0) {
                        try {
                            Thread.sleep(retryDelay);
                        } catch (InterruptedException ie) {
                            Thread.currentThread().interrupt();
                            throw ie;
                        }
                    }
                    continue;
                }

                return false;
            }
        } while (retryCount < maxRetries);

        return false;
    }

    /**
     * 检查中断状态
     */
    protected final void checkInterruption() throws InterruptedException {
        if (Thread.currentThread().isInterrupted()) {
            throw new InterruptedException("线程被中断");
        }
    }

    /**
     * 检查是否被中断
     */
    protected final boolean isInterrupted() {
        return Thread.currentThread().isInterrupted();
    }

    /**
     * 清理资源
     */
    private void cleanup(boolean activationAcquired) {
        if (activationAcquired) {
            try {
                ActivationManager.releaseActivation(targetWindow);
            } catch (Exception ex) {
                logger.error("[命令] 释放激活权失败: {}", ex.getMessage());
            }
        }
    }

    @Override
    public void setRetryConfig(int maxRetries, long retryDelay) {
        if (maxRetries < 0) {
            throw new IllegalArgumentException("最大重试次数不能为负数");
        }
        if (retryDelay < 0) {
            throw new IllegalArgumentException("重试延迟不能为负数");
        }
        this.maxRetries = maxRetries;
        this.retryDelay = retryDelay;
    }

    /**
     * 具体的命令执行逻辑
     */
    protected abstract void doExecute() throws Exception;
}